﻿using System.Text.RegularExpressions;
using Crux.Core.SQL.Formatter.Language;

namespace Crux.Core.SQL.Formatter.Core.Util;
/// <summary>
/// 
/// </summary>
public class RegexUtil
{
    private static readonly string EscapeRegex =
        string.Join("|",
            new List<string> { "^", "$", "\\", ".", "*", "+", "*", "?", "(", ")", "[", "]", "{", "}", "|" }
            .Select(spChr => "(\\" + spChr + ")"));
    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public static readonly Regex EscapeRegexPattern = new Regex(EscapeRegex);
    /// <summary>
    /// 
    /// </summary>
    /// <param name="s"></param>
    /// <returns></returns>
    public static string EscapeRegExp(string s)
    {
        return EscapeRegexPattern.Replace(s, @"\$0");
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="multiLetterOperators"></param>
    /// <returns></returns>
    public static string CreateOperatorRegex(JSLikeList<string> multiLetterOperators)
    {
        return string.Format("^({0}|.)",
            string.Join("|", Utils.SortByLengthDesc(multiLetterOperators).Map(EscapeRegExp).ToList()));
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="lineCommentTypes"></param>
    /// <returns></returns>
    public static string CreateLineCommentRegex(JSLikeList<string> lineCommentTypes)
    {
        return string.Format("^((?:{0}).*?)(?:\r\n|\r|\n|$)",
            string.Join("|", lineCommentTypes.Map(EscapeRegExp).ToList()));
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="reservedWords"></param>
    /// <returns></returns>
    public static string CreateReservedWordRegex(JSLikeList<string> reservedWords)
    {
        if (reservedWords.IsEmpty())
        {
            return "^\b$";
        }

        var reservedWordsPattern =
            string.Join("|", Utils.SortByLengthDesc(reservedWords).ToList()).Replace(" ", "\\s+");

        return "(?i)" + "^(" + reservedWordsPattern + ")\\b";
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="specialChars"></param>
    /// <returns></returns>
    public static string CreateWordRegex(JSLikeList<string> specialChars)
    {
        return "^([\\p{L}\\p{Nd}\\p{Mn}\\p{Pc}"
            + specialChars.Join("")
            + "]+)";
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="stringTypes"></param>
    /// <returns></returns>
    public static string CreateStringRegex(JSLikeList<string> stringTypes)
    {
        return "^(" + CreateStringPattern(stringTypes) + ")";
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="stringTypes"></param>
    /// <returns></returns>
    public static string CreateStringPattern(JSLikeList<string> stringTypes)
    {
        return string.Join("|", stringTypes.Map(StringLiteral.Get).ToList());
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="parens"></param>
    /// <returns></returns>
    public static string CreateParenRegex(JSLikeList<string> parens)
    {
        return "(?i)^(" + string.Join("|", parens.Map(EscapeParen).ToList()) + ")";
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="paren"></param>
    /// <returns></returns>
    public static string EscapeParen(string paren)
    {
        if (paren.Length == 1)
        {
            return EscapeRegExp(paren);
        }

        return "\\b" + paren + "\\b";
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="types"></param>
    /// <param name="pattern"></param>
    /// <returns></returns>
    public static Regex? CreatePlaceholderRegexPattern(JSLikeList<string> types, string pattern)
    {
        if (types.IsEmpty())
        {
            return null;
        }

        var typesRegex = string.Join("|", types.Map(EscapeRegExp).ToList());

        return new Regex(string.Format("^((?:{0})(?:{1}))", typesRegex, pattern));
    }
}